package com.hmjk.health.views;

import com.hmjk.health.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;

public class RefreshLayout extends LinearLayout{
	private static final String TAG = RefreshLayout.class.getSimpleName();
	private Context mContext;
	public static final int THEME_LOCATE= 0;
	public static final int THEME_HEALTH = 1; 
	public static final int THEME_SPORT = 2;
	private int mTheme = THEME_LOCATE;
	private LinearLayout mRefreshView;
	private TextView text;
	private ImageView icon;
	private int height = 0;
	private int padding = 0;
	private ScrollView sc;
	private OnRefreshListener listener;
	private RotateAnimation animRotateUp;
	private RotateAnimation animRotateDown;
	private Animation animCycle;
	private String upTime = null;
	
	private static final int STATE_NONE = 0;
	private static final int STATE_PULL = 1;
	private static final int STATE_RELEASE = 2;
	private static final int STATE_REFRESHING = 3;
	private int state = STATE_NONE;
	
	public interface OnRefreshListener{
		public void onRefresh();
	}
	
	private void logd(String info){
		Log.d(TAG, info);
	}
	
	public RefreshLayout(Context context) {
		super(context);
		mContext = context;
	}
	
	public RefreshLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		init(attrs);
	}
	
	public RefreshLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
		init(attrs);
	}
	
	private void init(AttributeSet attrs){
		
		LayoutInflater inflater = LayoutInflater.from(mContext);
		if(attrs != null){
			TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.RefreshLayout); 
			mTheme = a.getInt(R.styleable.RefreshLayout_theme, mTheme);
			a.recycle();  
		}
		
		mRefreshView = (LinearLayout)inflater.inflate(R.layout.refresh_header, null);
		text = (TextView)mRefreshView.findViewById(R.id.rtext);
		icon = (ImageView)mRefreshView.findViewById(R.id.ricon);
		if(mTheme == THEME_HEALTH){
			icon.setImageResource(R.drawable.health_pulldown);
		}else{
			icon.setImageResource(R.drawable.pulldown);
		}
		measureView();
		height = mRefreshView.getMeasuredHeight();
		padding = -1 * height;
		mRefreshView.setPadding(0, padding, 0, 0);
		mRefreshView.invalidate();
		
		animRotateUp = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animRotateUp.setInterpolator(new LinearInterpolator());
		animRotateUp.setDuration(200);
		animRotateUp.setFillAfter(true);
		animRotateDown = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animRotateDown.setInterpolator(new LinearInterpolator());
		animRotateDown.setDuration(200);
		animRotateDown.setFillAfter(true);
		animCycle = AnimationUtils.loadAnimation(mContext, R.anim.rotatecycled);
		addView(mRefreshView,0);
	}
	
	public void setTheme(int theme){
		mTheme = theme;
		if(icon != null){
			if(mTheme == THEME_HEALTH){
				icon.setImageResource(R.drawable.health_pulldown);
			}else{
				icon.setImageResource(R.drawable.pulldown);
			}
		}
	}
	
	public void setUpdateTime(long time){
		if(time > 0){
			Time t = new Time();
			t.setToNow();
			int cd = t.yearDay;
			t.set(time);
			int d = t.yearDay;
			if(d == cd){
				upTime = String.format("%02d:%02d", t.hour,t.minute);
			}else if((d+1) == cd){
				upTime = String.format("%02d:%02d", t.hour,t.minute);
				upTime = mContext.getResources().getString(R.string.yesterday,upTime);
			}else{
				upTime =  mContext.getResources().getString(R.string.upday,t.month,t.monthDay);
			}
		}else{
			upTime = null;
		}
	}
	
	public void setOnRefreshListener(OnRefreshListener l){
		listener = l;
	}
	
	public boolean isRefreshing(){
		return (STATE_REFRESHING == state);
	}
	
	public void stopRefreshing(){
		updateView(STATE_NONE);
		padding = -1 * height;
		logd("stopRefreshing:padding="+padding);
		mRefreshView.setPadding(0, padding, 0, 0);
	}
	
	private void updateView(int newstate){
		if((STATE_NONE == state) && (STATE_PULL == newstate)){
			state = newstate;
			logd("updateView none to pull");
			String txt;
			if(upTime != null)
				txt = mContext.getResources().getString(R.string.update_at,upTime);
			else
				txt = mContext.getResources().getString(R.string.pull_down);
			text.setText(txt);
			icon.clearAnimation();
			if(mTheme == THEME_HEALTH){
				icon.setImageResource(R.drawable.health_pulldown);
			}else{
				icon.setImageResource(R.drawable.pulldown);
			}
		}else if((STATE_PULL == state) && (STATE_RELEASE == newstate)){
			state = newstate;
			logd("updateView pull to release");
			text.setText(R.string.release_refresh);
			icon.clearAnimation();
			icon.startAnimation(animRotateUp);
		}else if((STATE_RELEASE == state) && (STATE_PULL == newstate)){
			state = newstate;
			logd("updateView release to pull");
			String txt = mContext.getResources().getString(R.string.update_at,"20:22");
			text.setText(txt);
			icon.clearAnimation();
			icon.startAnimation(animRotateDown);
		}else if((STATE_RELEASE == state) && (STATE_REFRESHING == newstate)){
			state = newstate;
			logd("updateView release to refreshing");
			text.setText(R.string.refreshing);
			icon.clearAnimation();
			icon.setImageResource(R.drawable.wait_small);
			icon.startAnimation(animCycle);
		}else if(newstate == STATE_NONE){
			state = newstate;
			logd("updateView newstate="+newstate);
			String txt = mContext.getResources().getString(R.string.update_at,"20:22");
			text.setText(txt);
			icon.clearAnimation();
			if(mTheme == THEME_HEALTH){
				icon.setImageResource(R.drawable.health_pulldown);
			}else{
				icon.setImageResource(R.drawable.pulldown);
			}
		}
	}
	
	public void initScroll(){
		sc = (ScrollView)this.findViewById(R.id.refresh_scroll);
		sc.setOnTouchListener(new OnTouchListener(){
			private int beginY = -1;
			@Override
			public boolean onTouch(View v, MotionEvent ev) {
				switch(ev.getAction()){
				case MotionEvent.ACTION_MOVE:{
					
					logd("move: y="+ev.getY() + " s = "+state + " scroll = " + sc.getScrollY());
					logd("move: beginY = "+beginY);
					if(((sc.getScrollY() == 0) && (STATE_NONE == state))||
							(state == STATE_PULL) || (state == STATE_RELEASE)){
						
						if(beginY == -1)
							beginY = (int) ev.getY();
						
						int y = (int) ev.getY();
						int h = y - beginY;
						if(h > 0){
							h = h/3;
							padding = -1 * height + h;
							if(padding > (2 * height)){
								padding = 2 * height;
							}
							logd("move: padding="+padding);
							mRefreshView.setPadding(0, padding, 0, 0);
							if(padding > 0){
								updateView(STATE_RELEASE);
							}else{
								updateView(STATE_PULL);
							}
							
						}
					}
				}
				break;
				case MotionEvent.ACTION_UP:
				case MotionEvent.ACTION_CANCEL:{
					beginY = -1;
					logd("up_cancel: act="+ ev.getAction()+" : s = "+state);
					if(state == STATE_RELEASE){
						updateView(STATE_REFRESHING);
						padding = 0;
						logd("up_cancel: padding = 0");
						mRefreshView.setPadding(0, padding, 0, 0);
						//show animation
						if(listener != null)
							listener.onRefresh();
					}else if(state == STATE_PULL){
						updateView(STATE_NONE);
						padding = -1 * height;
						logd("up_cancel: padding = "+padding);
						mRefreshView.setPadding(0, padding, 0, 0);
					}
				}
				break;
				case MotionEvent.ACTION_DOWN:{
					logd("down: y="+ev.getY() + " s = "+state + " scroll = " + sc.getScrollY());
					if(sc.getScrollY() == 0){
					beginY = (int) ev.getY();
					logd("down: y="+ev.getY() + " s = "+state);
					}
				}
				break;
				}
				
				if(padding > (-1 * height) && (state != STATE_REFRESHING)){
					logd("return true");
					return true;
				}else{
					logd("return false");
					return false;
				}
			}
			
		});
	}

	private void measureView(){
		ViewGroup.LayoutParams p = mRefreshView.getLayoutParams();
		if(p == null){
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);	
		}
		int childwspec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
		//int w = p.width;
		int h = p.height;
		int childhspec;
		if(h > 0){
			childhspec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
		}else{
			childhspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		
		mRefreshView.measure(childwspec, childhspec);
	}
}
